package com.my.code.samphore;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Semaphore;

/**
 * 使用Semaphore构造池子对象
 *
 * @param <T>
 */
public class Pool<T> {
    private int size;
    private List<T> items = new ArrayList<>();
    private volatile boolean[] checkedOut;
    private final Semaphore available;//semaphore 控制许可证数量

    public Pool(int size, Class<T> clazz) {
        this.size = size;
        checkedOut = new boolean[size];
        available = new Semaphore(size, true);
        for (int i = 0; i < size; i++) {
            try {
                items.add(clazz.getDeclaredConstructor().newInstance());//T 需要默认构造器
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    }

    public T checkOut() throws InterruptedException {
        available.acquire();
        return getItem();
    }

    public void checkIn(T t) {
        if (preCheck(t)) {
            available.release();
        } else {
            System.out.println("check in ignore: " + t);
        }

    }

    private synchronized T getItem() {
        for (int i = 0; i < size; i++) {
            if (!checkedOut[i]) {
                checkedOut[i] = true;
                return items.get(i);
            }
        }
        return null;//semaphore prevents reaching here
    }

    private synchronized boolean preCheck(T item) {
        int index = items.indexOf(item);
        if (index == -1) return false;//not in the list
        if (checkedOut[index]) {
            checkedOut[index] = false;
            return true;
        }
        return false;//wasn't checked out
    }
}
